package com.lenovo.agricultureclient.request;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import org.json.JSONException;
import org.json.JSONObject;

import com.lenovo.agricultureclient.AppConfig;
import com.lenovo.agricultureclient.ClientApp;
import com.lenovo.agricultureclient.request.BaseRequest.RequestResult;
import com.lenovo.agricultureclient.util.NetUtil;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Base64;
import android.util.Log;
/**
 * 请求执行线程,支持http和socket两种通信方式，其端口设置见AppConfig文件
 * 该线程既可以执行一次请求然后就结束，也可以循环重复执行同一个请求，isLoop变量可以进行控制
 * @author zongbingwu
 *
 */
public class RequestThread extends Thread 
{
	private static final String TAG = "RequestThread";
	//日志开关
	private static final boolean LOG_ENABLE = true;
	
	//支持http和socket两种通信方式
	public static final String COMMUN_HTTP 		= "http";
	public static final String COMMUN_SOCKET	= "socket";
	//消息id,请求完成以后，需要将此id发送给ui主线程处理
	public static final int MSG_REQUEST_RESULT = 0x10;
	//ui主线程的Handler
	private Handler mHandler;
	//app上下文
	private Context mContext;
	//通信方式
	private String mCommunType;
	//请求实体对象
	private BaseRequest mRequest;
	//app对象
	private ClientApp mApp;
	
	//线程是否已经被取消的控制变量
	private volatile boolean mCancel = false;
	//线程是否应该循环执行的控制变量
	private volatile boolean isLoop = false;
	//循环执行的时间间隔
	private volatile int loopPeriod = 1000;//默认为1秒
	//线程是否已经被暂停的控制变量
	private volatile boolean isPause = false;
	
	public RequestThread(String communType, Context context, Handler handler)
	{
		mContext = context;
		mHandler = handler;
		this.mCommunType = communType;
		mApp = (ClientApp)context.getApplicationContext();
	}
	//请求执行线程装载请求实体
	public void setRequest(BaseRequest mRequest) {
		this.mRequest = mRequest;
	}
	//停止请求线程
	public void stopRequestThread()
	{
		mCancel = true;
		isLoop = false;
	}
	//请求线程是否已经停止
	public boolean isCancel()
	{
		return mCancel;
	}
	//打印日志
	private void showLog(String msg)
	{
		if(LOG_ENABLE){
			Log.d(TAG,msg);
		}
	}
	
	@Override
	public void run() 
	{
		super.run();
		do 
		{
			if(!isPause)
			{
				RequestResult result = RequestResult.RESULT_FAIL;
				//先判断网络状态
				if(NetUtil.isNetworkAvailable(mContext))
				{
					try 
					{
						if(mRequest!=null && mApp!=null)
						{
							//获取协议类型
							String protocolType = mRequest.getProtocolType();
							//获取action名称
							String actionName = mRequest.getActionName();
							//获取请求body
							String requestBody = mRequest.getBody();
							if(protocolType!=null && actionName!=null && requestBody!=null)
							{
								//采用http POST的通信方式
								if(mCommunType.equals(COMMUN_HTTP))
								{
									//url组装
									String url = "http://"+mApp.getServerIpStr()+":"+AppConfig.HTTP_SERVER_PORT;
									url += "/type/"+protocolType;//设置协议类型
									url += "/action/"+actionName;//设置action名称
									showLog("Http Url:"+url);
									showLog("Http body:"+requestBody);
									String response = "";
									
									//jason 跟 soap的http请求格式有点区别，因此分别调用了两个不同的函数
									if(protocolType.equals(BaseRequest.PROTOCOL_JASON)){
										response = NetUtil.sendByPost(url, requestBody);//采用http post的方式发送jason报文
									} else if(protocolType.equals(BaseRequest.PROTOCOL_SOAP)){
										response = NetUtil.sendSoap(url, actionName, requestBody);//采用http post的方式发送soap报文
									}
									//将服务器端回应的结果保存到请求对象中
									mRequest.setResponseStr(response);
									showLog("Http response:"+response);
									result = RequestResult.RESULT_SUCCESS;
								}
								else if(mCommunType.equals(COMMUN_SOCKET))//采用socket通信方式
								{
									String outMsg = "";
									//封装请求数据
									//body字段的内容需要经过Base64编码
									String bodyBase64 = Base64.encodeToString(requestBody.getBytes(), Base64.DEFAULT);
									JSONObject jsonObj = new JSONObject();
									try 
									{
										jsonObj.put("type", protocolType);//设置协议类型
										jsonObj.put("action", actionName);//设置action名称
										jsonObj.put("body", bodyBase64);//设置body内容
										outMsg = jsonObj.toString();
									} 
									catch (JSONException e) {
										e.printStackTrace();
									}
									
									String receiveMsg = "";
									//采用socket通信方式
									Socket clientSocket = null;
									try
									{
										clientSocket = new Socket(mApp.getServerIpStr(), AppConfig.SOCKET_SERVER_PORT);
										clientSocket.setSoTimeout(30*1000);//设置超时
										BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
										//先向服务器端发送数据，以后回车为结束标记
							            PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
							            out.println(outMsg);
							            out.flush();
							            
							            //再读取服务器端的回应数据，一行一行的读取
							            String line;
							            while ((line = in.readLine()) != null)
							            {
							            	if(line.equals("")){
							            		break;
							            	}
							            	receiveMsg += line;
							            }
									}
									catch(UnknownHostException e){
										e.printStackTrace();
									}
									catch(IOException e){
										e.printStackTrace();
									}
									finally
									{
										if(clientSocket!=null)
										{
											clientSocket.close();
										}
									}
									
									//数据解析，Base64解码
									byte tmpB[] = Base64.decode(receiveMsg, Base64.DEFAULT);
									String receBody = new String(tmpB);
									//将服务器端回应的结果保存到请求对象中
									mRequest.setResponseStr(receBody);
									showLog("socket response:"+receBody);
									result = RequestResult.RESULT_SUCCESS;
								}
							}
						}
					} 
					catch (Exception e)
					{
						result = RequestResult.RESULT_FAIL;	
						e.printStackTrace();
					}
				}
				else
				{
					result = RequestResult.RESULT_NO_NET;
				}
				
				//请求完成以后，将此结果发送给ui主线程处理
				if(!mCancel && mHandler!=null)
				{
					Message msg = new Message();
					msg.what = MSG_REQUEST_RESULT;
					msg.obj = this;
					msg.arg1 = result.ordinal();
					mHandler.sendMessage(msg);
				}
				
				//如果时循环执行线程，则延时
				if(isLoop)
				{
					try {
						Thread.sleep(loopPeriod);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
			else 
			{
				//如果线程被暂停，则线程延时
				try {
					Thread.sleep(loopPeriod);
					continue;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		} while (isLoop);
	}
	//该函数只能由ui主线程来调用，其他线程不能调用，目的是让ui主线程处理请求结果，以便界面刷新
	public void hanlderResult(RequestResult result)
	{
		if(!mCancel && mRequest!=null)
		{
			mRequest.parseResult(result);
		}
	}
	//判断线程是否暂停
	public void pause(){
		isPause = true;
	}
	//线程重新开始
	public void restart(){
		isPause = false;
	}
	//设置线程是否为循环执行
	public void setLoop(boolean isLoop, int loopPeriod)
	{
		this.isLoop = isLoop;
		this.loopPeriod = loopPeriod;
	}
}
